{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. 组织文件笔记（第9章）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**1.1 文件与文件路径**  \n",
    "通过import shutil调用shutil模块操作目录，shutil模块能够在Python 程序中实现文件复制、移动、改名和删除；同时也介绍部分os操作文件的函数。常用函数如下：\n",
    "\n",
    "|函数|用途|备注|\n",
    "|---|---|---|\n",
    "|shutil.copy(source, destination)|复制文件||\n",
    "|shutil.copytree(source, destination)|复制文件夹|如果文件夹不存在，则创建文件夹|\n",
    "|shutil.move(source, destination)|移动文件|返回新位置的绝对路径的字符串，且会覆写文件|\n",
    "|os.unlink(path)|删除path处的文件||\n",
    "|os.rmdir(path)|删除path处的文件夹|该文件夹必须为空，其中没有任何文件和文件|\n",
    "|shutil.rmtree(path)|删除path处的文件夹|包含的所有文件和文件夹都会被删除|\n",
    "|os.walk(path)|遍历path下所有文件夹和文件|返回3个值：当前文件夹名称，当前文件夹子文件夹的字符串列表，当前文件夹文件的字符串列表|、\n",
    "|os.rename(path)|path处文件重命名||"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**1.2 用zipfile 模块压缩文件**  \n",
    "通过import zipfile，利用zipfile模块中的函数，Python 程序可以创建和打开（或解压）ZIP 文件。常用函数如下：  \n",
    "\n",
    "|函数|用途|备注|\n",
    "|---|---|---|\n",
    "|exampleZip=zipfile.ZipFile('example.zip')|创建一个ZipFile对象|example.zip表示.zip 文件的文件名|\n",
    "|exampleZip.namelist()|返回ZIP 文件中包含的所有文件和文件夹的字符串的列表||\n",
    "|spamInfo = exampleZip.getinfo('example.txt')|返回一个关于特定文件的ZipInfo 对象|example.txt为压缩文件中的某一文件|\n",
    "|spamInfo.file_size|返回源文件大小|单位字节|\n",
    "|spamInfo.compress_size|返回压缩后文件大小|单位字节|\n",
    "|exampleZip.extractall(path))|解压压缩文件到path目录|path不写，默认为当前目录|\n",
    "|exampleZip.extract('spam.txt', path)|提取某一压缩文件当path目录|path不写，默认为当前目录|\n",
    "|newZip = zipfile.ZipFile('new.zip', 'w')|以“写模式”打开ZipFile 对象||\n",
    "|newZip.write('spam.txt', compress_type=zipfile.ZIP_DEFLATED)|压缩文件|第一个参数是要添加的文件。第二个参数是“压缩类型”参数|\n",
    "|newZip.close()|关闭ZipFile对象||"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. 项目练习"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.1 将带有美国风格日期的文件改名为欧洲风格日期"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Renaming \"d:\\今天是06-28-2019.txt\" to \"d:\\今天是28-06-2019.txt\"...\n"
     ]
    }
   ],
   "source": [
    "# 导入模块\n",
    "import shutil\n",
    "import os\n",
    "import re\n",
    "# Renames filenames with American MM-DD-YYYY date format to European DD-MM-YYYY.\n",
    "\n",
    "# 含美国风格的日期\n",
    "# Create a regex that matches files with the American date format.\n",
    "datePattern = re.compile(\n",
    "    # 匹配文件名开始处、日期出现之前的任何文本\n",
    "    r\"\"\"^(.*?) # all text before the date\n",
    "        # 匹配月份\n",
    "        ((0|1)?\\d)- # one or two digits for the month\n",
    "        # 匹配日期\n",
    "        ((0|1|2|3)?\\d)- # one or two digits for the day\n",
    "        # 匹配年份\n",
    "        ((19|20)\\d\\d) # four digits for the year\n",
    "        (.*?)$ # all text after the date\n",
    "        \"\"\", re.VERBOSE)\n",
    "\n",
    "# 查找路径\n",
    "searchPath='d:/'\n",
    "\n",
    "for amerFilename in os.listdir(searchPath):\n",
    "    mo = datePattern.search(amerFilename)\n",
    "    # Skip files without a date.\n",
    "    if mo == None:\n",
    "        continue\n",
    "    # Get the different parts of the filename.\n",
    "    # 识别日期\n",
    "    beforePart = mo.group(1)\n",
    "    monthPart = mo.group(2)\n",
    "    dayPart = mo.group(4)\n",
    "    yearPart = mo.group(6)\n",
    "    afterPart = mo.group(8)\n",
    "\n",
    "    # Form the European-style filename. 改为欧洲式命名\n",
    "    euroFilename = beforePart + dayPart + '-' + \\\n",
    "        monthPart + '-' + yearPart + afterPart\n",
    "    # Get the full, absolute file paths.\n",
    "    # 返回绝对路径\n",
    "    absWorkingDir = os.path.abspath(searchPath)\n",
    "    # 原文件名\n",
    "    amerFilename = os.path.join(absWorkingDir, amerFilename)\n",
    "    # 改后文件名\n",
    "    euroFilename = os.path.join(absWorkingDir, euroFilename)\n",
    "    # Rename the files.\n",
    "    print('Renaming \"%s\" to \"%s\"...' % (amerFilename, euroFilename))\n",
    "    shutil.move(amerFilename, euroFilename)  # uncomment after testing"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.2 将一个文件夹备份到一个ZIP 文件"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Creating image_1.zip...\n",
      "Done.\n",
      "Done.\n"
     ]
    }
   ],
   "source": [
    "\n",
    "import zipfile\n",
    "import os\n",
    "\n",
    "\n",
    "# 弄清楚ZIP 文件的名称\n",
    "def backupToZip(folder):\n",
    "    # Backup the entire contents of \"folder\" into a ZIP file.\n",
    "    # 获得文件夹绝对路径\n",
    "    folder = os.path.abspath(folder)  # make sure folder is absolute\n",
    "    # Figure out the filename this code should use based on\n",
    "    # what files already exist.\n",
    "    number = 1\n",
    "    while True:\n",
    "        # 压缩文件名\n",
    "        zipFilename = os.path.basename(folder) + '_' + str(number) + '.zip'\n",
    "        # 如果压缩文件不存在\n",
    "        if not os.path.exists(zipFilename):\n",
    "            break\n",
    "        number = number + 1\n",
    "\n",
    "    # Create the ZIP file.\n",
    "    print('Creating %s...' % (zipFilename))\n",
    "    # 创建新ZIP 文件\n",
    "    backupZip = zipfile.ZipFile(zipFilename, 'w')\n",
    "    # TODO: Walk the entire folder tree and compress the files in each folder.\n",
    "    print('Done.')\n",
    "\n",
    "    # 提取文件目录\n",
    "    # 一层一层获得目录\n",
    "    # Walk the entire folder tree and compress the files in each folder.\n",
    "    for foldername, subfolders, filenames in os.walk(folder):\n",
    "        print('Adding files in %s...' % (foldername))\n",
    "\n",
    "        # 压缩文件夹\n",
    "        # Add the current folder to the ZIP file.\n",
    "        backupZip.write(foldername)\n",
    "\n",
    "        # Add all the files in this folder to the ZIP file.\n",
    "        for filename in filenames:\n",
    "            newBase = os.path.basename(folder) + '_'\n",
    "            # 判断文件是否是压缩文件\n",
    "            if filename.startswith(newBase) and filename.endswith('.zip'):\n",
    "                continue  # don't backup the backup ZIP files\n",
    "            backupZip.write(os.path.join(foldername, filename))\n",
    "    backupZip.close()\n",
    "    print('Done.')\n",
    "\n",
    "\n",
    "backupToZip('image')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.3 选择性拷贝  \n",
    "编写一个程序，遍历一个目录树，查找特定扩展名的文件（诸如.pdf 或.jpg）。不论这些文件的位置在哪里，将它们拷贝到一个新的文件夹中。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "import shutil\n",
    "import os\n",
    "\n",
    "\n",
    "def searchFile(path, savepath):\n",
    "    # 判断要保存的文件夹路径是否存在\n",
    "    if not os.path.exists(savepath):\n",
    "        # 创建要保存的文件夹\n",
    "        os.makedirs(savepath)\n",
    "    # 遍历文件夹\n",
    "    for foldername, subfolders, filenames in os.walk(path):\n",
    "        for filename in filenames:\n",
    "            # 判断是不是txt或者pdf文件\n",
    "            if filename.endswith('txt') or filename.endswith('pdf'):\n",
    "                inputFile = os.path.join(foldername, filename)\n",
    "                # 保存文件路径\n",
    "                outputFile = os.path.join(savepath, filename)\n",
    "                # 文件保存\n",
    "                shutil.copy(inputFile, outputFile)\n",
    "\n",
    "\n",
    "searchFile(\"mytest\", \"save\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.4 删除不需要的文件  \n",
    "编写一个程序，遍历一个目录树，查找特别大的文件或文件夹。将这些文件的绝对路径打印到屏幕上。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "import os\n",
    "\n",
    "\n",
    "def deletefile(path):\n",
    "    for foldername, subfolders, filenames in os.walk(path):\n",
    "        for filename in filenames:\n",
    "            # 绝对路径\n",
    "            filepath = os.path.join(foldername, filename)\n",
    "            # 如果文件大于100MB\n",
    "            if os.path.getsize(filepath)/1024/1024 > 100:\n",
    "                # 获得绝对路径\n",
    "                filepath = os.path.abspath(filepath)\n",
    "                print(filepath)\n",
    "                # 删除文件\n",
    "                os.unlink(filepath)\n",
    "\n",
    "\n",
    "deletefile(\"mytest\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.5 消除缺失的编号  \n",
    "编写一个程序，在一个文件夹中，找到所有带指定前缀的文件，诸如spam001.txt,spam002.txt 等，并定位缺失的编号（例如存在spam001.txt 和spam003.txt，但不存在spam002.txt）。让该程序对所有后面的文件改名，消除缺失的编号。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "the missing number file is .\\spam005.txt:\n"
     ]
    }
   ],
   "source": [
    "\n",
    "import os\n",
    "import re\n",
    "# 路径地址\n",
    "path = '.'\n",
    "fileList = []\n",
    "numList = []\n",
    "# 寻找文件\n",
    "pattern = re.compile('spam(\\d{3}).txt')\n",
    "for file in os.listdir(path):\n",
    "    mo = pattern.search(file)\n",
    "    if mo != None:\n",
    "        fileList.append(file)\n",
    "        numList.append(mo.group(1))\n",
    "\n",
    "# 对存储的文件排序\n",
    "fileList.sort()\n",
    "numList.sort()\n",
    "\n",
    "# 开始缺失的文件编号\n",
    "# 编号从1开始\n",
    "index = 1\n",
    "# 打印不连续的文件\n",
    "for i in range(len(numList)):\n",
    "    # 如果文件编号不连续\n",
    "    if int(numList[i]) != i+index:\n",
    "        inputFile = os.path.join(path, fileList[i])\n",
    "        print(\"the missing number file is {}:\".format(inputFile))\n",
    "        outputFile = os.path.join(path, 'spam'+'%03d' % (i+1)+'.txt')\n",
    "        os.rename(inputFile, outputFile)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
